/********************************
功  能：定时/计数器实现按键可调电子时钟
编程人：ZZT
版  本：V1.0
时  间：2023/12/23
**********************************/
//头文件声明
#include <Reg51.h>
#include "display.h"
#include "delay.h"

//全局变量声明
unsigned char timerCnt;//秒的计数标志
unsigned char sec;//60秒计时
unsigned char min;//60分计时
unsigned char hour;//24小时计时
unsigned char state;//按键的标志变量，更换模式

//函数声明
void Timer0Init(void);//定时器0初始化
void Timer1Init(void);//定时器1初始化
void showNormal();//时间界面显示
void EX0_Init();//外部中断0初始化
void EX1_Init();//外部中断1初始化
void showSec();//调秒显示界面显示
void showMin();//调分显示界面显示
void showHour();//调时显示界面显示

/**********************************
函数名：main
功  能：完成程序模块的调用
参  数：无
返回值：无
***********************************/
void main()
{
	EX0_Init();
	EX1_Init();
	Timer1Init();
	Timer0Init();
	EA = 1;
	while(1)
	{
		switch(state)
		{
			case 0:TR0 = 1;showNormal();break;//正常时钟状态
			case 1:showSec();break;//调秒
			case 2:showMin();break;//调分
			case 3:showHour();break;//调时
			default:break;
		}
	}
}

/**********************************
函数名：EX0_Init
功  能：外部中断0初始化
参  数：无
返回值：无
***********************************/
void EX0_Init()
{
	IT0 = 1;
	EX0 = 1;
}

/**********************************
函数名：EX1_Init
功  能：外部中断1初始化
参  数：无
返回值：无
***********************************/
void EX1_Init()
{
	IT1 = 1;
	EX1 = 1;
}

/**********************************
函数名：showNormal
功  能：将时、分、秒存储在数据缓冲区
参  数：无
返回值：无
***********************************/
void showNormal()
{
	LEDBuff[0] = hour / 10;
	LEDBuff[1] = hour % 10;
	LEDBuff[2] = min / 10;
	LEDBuff[3] = min % 10;
	LEDBuff[4] = sec / 10;
	LEDBuff[5] = sec % 10;
}

/**********************************
函数名：showSec
功  能：将调秒的秒数存储在数据缓冲区，时、分熄灭
参  数：无
返回值：无
***********************************/
void showSec()
{
	LEDBuff[0] = 23;
	LEDBuff[1] = 23;
	LEDBuff[2] = 23;
	LEDBuff[3] = 23;
	LEDBuff[4] = sec / 10;
	LEDBuff[5] = sec % 10;
}

/**********************************
函数名：showMin
功  能：将调分的分钟数存储在数据缓冲区，时、秒熄灭
参  数：无
返回值：无
***********************************/
void showMin()
{
	LEDBuff[0] = 23;
	LEDBuff[1] = 23;
	LEDBuff[2] = min / 10;
	LEDBuff[3] = min % 10;
	LEDBuff[4] = 23;
	LEDBuff[5] = 23;
}

/**********************************
函数名：showHour
功  能：将调时的小时数存储在数据缓冲区，秒、分熄灭
参  数：无
返回值：无
***********************************/
void showHour()
{
	LEDBuff[0] = hour / 10;
	LEDBuff[1] = hour % 10;
	LEDBuff[2] = 23;
	LEDBuff[3] = 23;
	LEDBuff[4] = 23;
	LEDBuff[5] = 23;
}

/**********************************
函数名：Timer0Init
功  能：定时器0初始化
参  数：无
返回值：无
***********************************/
void Timer0Init(void)		//50毫秒@11.0592MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0x4C;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	ET0 = 1;
	//TR0 = 1;		//定时器0开始计时
}

/**********************************
函数名：Timer1Init
功  能：定时器1初始化
参  数：无
返回值：无
***********************************/
void Timer1Init(void)		//1毫秒@11.0592MHz
{
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x10;		//设置定时器模式
	TL1 = 0x66;		//设置定时初值
	TH1 = 0xFC;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	ET1 = 1;
	TR1 = 1;		//定时器1开始计时
}

/************************************
1、中断服务函数一定是一个没有返回值的函数
2、中断服务函数一定是没有参数的函数
3、中断服务函数函数名后跟关键字 interrupt
4、interrupt n 0 - 4  5个中断源     8 * n + 0003H 
   0003H INT0 00BH T0 0013H INT1 001BH T1 0023H ES
5、中断服务函数不能被主程序或其他程序所调用
6、n 后面 跟 using m (0 - 3) 工作寄存器组
***************************************/
void Timer0_ISR(void) interrupt 1
{
	timerCnt++;
	if (timerCnt++ >= 20)//20次50ms中断，即1s时间到
	{
		timerCnt = 0;
		sec++;
		if (sec >= 60)//60秒到sec清零，分+1
		{
			sec = 0;
			min++;
			if (min >= 60)//60分到min清零，时+1
			{
				min = 0;
				hour++;
				if (hour >= 24)
				{
					hour = 0;//60分到hour清零
				}
			}
		}
	}
	TL0 = 0x00;		//设置定时初值
	TH0 = 0x4C;		//设置定时初值
}

void Timer1_ISR(void) interrupt 3
{
	TR1 = 0;
	Display();		//数码管动态显示
	TL1 = 0x66;		//设置定时初值
	TH1 = 0xFC;		//设置定时初值
	TR1 = 1;
}

void EX0_ISR() interrupt 0
{
	TR0 = 0;		//关闭定时器0
	DelayXms(10);	//消抖
	if (INT0 == 0)	//按键按下
	{
		state++;		
		if(state > 3)
			state = 0;
	}
}

void EX1_ISR() interrupt 2
{
	
	switch(state)
	{
		case 0:break;
		case 1:sec++;if(sec >= 60) sec = 0;break;//调秒达60秒清零
		case 2:min++;if(min >= 60) min = 0;break;//调分达60分清零
		case 3:hour++;if(hour >= 24) hour = 0;break;//调时达24时清零
		default:break;
	}
}